#!/bin/sh

MOD_NAME=url_blocker
MOD_DEFAULTS=/opt/$MOD_NAME/etc/defaults
MOD_SETTINGS=/opt/$MOD_NAME/etc/settings

WEB_SERVER=hiawatha
WEB_SERVER_EXEC=/opt/$MOD_NAME/usr/sbin/$WEB_SERVER
WEB_PORT_BP=8898

CONF_DIR=/var/$MOD_NAME
[ -d $CONF_DIR ] || mkdir $CONF_DIR
DNSMASQ_CONF_DIR=$CONF_DIR/dm_conf
[ -d $DNSMASQ_CONF_DIR ] || mkdir $DNSMASQ_CONF_DIR
VIRT_CONF_DIR=$CONF_DIR/bp_conf
[ -d $VIRT_CONF_DIR ] || mkdir $VIRT_CONF_DIR
VIRT_CONF=$VIRT_CONF_DIR/hiawatha.conf
WWW_DIR=$CONF_DIR/www
[ -d $WWW_DIR ] || mkdir $WWW_DIR

IPT_LIST="/sbin/iptables"
IP_PROG="/sbin/ip"
CHAIN_FWIN=mod_$MOD_NAME
VIRTUAL_IP="100.64.255.255"

[ -f "$MOD_SETTINGS" ] || cp $MOD_DEFAULTS $MOD_SETTINGS
. $MOD_SETTINGS

url_to_hex() {

  echo "$1" |
  awk '{
    for(n = 0; n < 256; n++) {
      ord[sprintf("%c", n)] = n;
    }
    i = split($1, arr, ".");
    for (j = 1; j <= i; j++) {
      printf "%02x ", length(arr[j]);
      for (k = 1; k <= length(arr[j]); k++) {
        nib = substr(arr[j], k, 1);
        printf "%02x ", ord[nib];
      }
    }
  }'
}

add_ipt_rules() {
  tmp=$(grep "URL[0-9]" $MOD_SETTINGS)
  for CFG_LINE in $tmp; do
    URL=${CFG_LINE#*=}
    [ -n "$URL" ] || continue;
    URL=$(echo "$URL" | awk '{print tolower($0)}')
    URL=${URL#www.}
    LEN=${#URL}
    POS=$(($LEN - 2))
    if [ ".*" == "${URL:$POS:2}" ]; then
      URL=${URL:0:$POS}
      HEXURL="$(url_to_hex $URL)""02"
      $IPT -A $CHAIN_FWIN -m string --algo bm --icase --hex-string "|$HEXURL|" -j REJECT
      HEXURL="$(url_to_hex $URL)""03"
      $IPT -A $CHAIN_FWIN -m string --algo bm --icase --hex-string "|$HEXURL|" -j REJECT
    else
      HEXURL=$(url_to_hex $URL)
      $IPT -A $CHAIN_FWIN -m string --algo bm --icase --hex-string "|$HEXURL|" -j REJECT
    fi
  done
}

add_dnsmasq_conf() {
  tmp=$(grep "URL[0-9]" $MOD_SETTINGS)
  echo "" > /$DNSMASQ_CONF_DIR/blocker.dnsmasq.conf
  for CFG_LINE in $tmp; do
    URL=${CFG_LINE#*=}
    [ -n "$URL" ] || continue;
    URL=$(echo "$URL" | awk '{print tolower($0)}')
    URL=${URL#www.}
    echo "address=/$URL/$VIRTUAL_IP" >> /$DNSMASQ_CONF_DIR/blocker.dnsmasq.conf
    echo "address=/www.$URL/$VIRTUAL_IP" >> /$DNSMASQ_CONF_DIR/blocker.dnsmasq.conf
  done
}

run_web_server() {
  ln -sf /opt/$MOD_NAME/etc/hiawatha/mimetype.conf $VIRT_CONF_DIR/mimetype.conf
  cat /opt/$MOD_NAME/etc/hiawatha/hiawatha.conf                          > $VIRT_CONF
  echo "PIDFile = /var/run/hiawatha_bp.pid"                              >> $VIRT_CONF
  echo "ErrorHandler = 404:/index.html"                                  >> $VIRT_CONF
  echo ""                                                                >> $VIRT_CONF
  echo "Binding {"                                                       >> $VIRT_CONF
  echo "    Port = $WEB_PORT_BP"                                         >> $VIRT_CONF
  echo "    TimeForRequest = 5, 1"                                       >> $VIRT_CONF
  echo "}"                                                               >> $VIRT_CONF

  sleep 2
  $WEB_SERVER_EXEC -c $VIRT_CONF_DIR
}

stop_web_server() {
  killall -0 $WEB_SERVER 2>/dev/null
  if [ $? -ne 0 ]; then
    echo "web server skipped";
    return 0;
  fi
  killall $WEB_SERVER 2>/dev/null
}

case "$1" in
  start)
    echo -n "Starting module $MOD_NAME: "
    if [ "$MOD_URLBLOCKER_ENABLED" != "1" ]; then
      echo "skipped"
      exit 0
    fi
    if [ "$MOD_URLBLOCKER_MODE" == "1" ]; then
      add_dnsmasq_conf
      /etc/init.d/dns stop
      /etc/init.d/dns start
      TGZ_FILE=$VIRT_CONF_DIR/tmp.tgz
      /opt/$MOD_NAME/bin/decode "$MOD_URLBLOCKER_BP" > $TGZ_FILE
      tar -xzf "$TGZ_FILE" -C $WWW_DIR
      rm -f "$TGZ_FILE"
      run_web_server
    fi
    for IPT in $IPT_LIST; do
      [ -x $IPT ] || continue;
      $IPT -N $CHAIN_FWIN
      if [ "$MOD_URLBLOCKER_MODE" == "1" ]; then
        $IPT -t nat -I PREROUTING -d $VIRTUAL_IP -p tcp --dport 80  -j REDIRECT --to-ports $WEB_PORT_BP
        $IPT -t nat -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53
        $IPT -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53
      else
        add_ipt_rules
      fi
      $IPT -I FORWARD -p udp --dport 53 -j $CHAIN_FWIN &>/dev/null
      $IPT -I FORWARD -p tcp --dport 53 -j $CHAIN_FWIN &>/dev/null
      $IPT -I INPUT -p udp --dport 53 -j $CHAIN_FWIN &>/dev/null
      $IPT -I INPUT -p tcp --dport 53 -j $CHAIN_FWIN &>/dev/null
    done
    if [ $? -ne 0 ]; then
      echo "failed"
      exit 1
    fi
    echo "done"
    exit 0;
    ;;
  stop)
    echo -n "Stopping module $MOD_NAME: "
    stop_web_server
    rm -rf /var/$MOD_NAME &>/dev/null
    rm -f /$DNSMASQ_CONF_DIR/blocker.dnsmasq.conf &>/dev/null
    /etc/init.d/dns stop
    /etc/init.d/dns start
    for IPT in $IPT_LIST; do
      [ -x $IPT ] || continue;
      $IPT -t nat -D PREROUTING -d $VIRTUAL_IP -p tcp --dport 80 -j REDIRECT --to-ports $WEB_PORT_BP &>/dev/null
      $IPT -t nat -D PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 &>/dev/null
      $IPT -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 &>/dev/null
      $IPT -D FORWARD -p udp --dport 53 -j $CHAIN_FWIN &>/dev/null
      $IPT -D FORWARD -p tcp --dport 53 -j $CHAIN_FWIN &>/dev/null
      $IPT -D INPUT -p udp --dport 53 -j $CHAIN_FWIN &>/dev/null
      $IPT -D INPUT -p tcp --dport 53 -j $CHAIN_FWIN &>/dev/null
      $IPT -F $CHAIN_FWIN &>/dev/null
      $IPT -X $CHAIN_FWIN &>/dev/null
    done
    if [ $? -ne 0 ]; then
      echo "failed"
      exit 1
    fi
    echo "done"
    exit 0;
    ;;
  restart)
    $0 stop
    $0 start
    exit 0;
    ;;
  status)
    echo -n "Module $MOD_NAME is "
    if [ "$MOD_URLBLOCKER_ENABLED" != "1" ]; then
      echo "disabled"
    else
      echo "enabled"
    fi
    exit 0;
    ;;
  defaults)
    cp $MOD_DEFAULTS $MOD_SETTINGS 2>/dev/null
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status|defaults}"
    exit 1
esac
